/**
 Copyright (c) 2011 Daniele Biagi
Permission is hereby granted, free of charge, to any person obtaining a copy of this 
software and associated documentation files (the "Software"), to deal in the Software 
without restriction, including without limitation the rights to use, copy, modify, 
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
permit persons to whom the Software is furnished to do so, subject to the following 
conditions:

The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 
OR OTHER DEALINGS IN THE SOFTWARE.
 */
package easyDLXGUI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.html.HTMLDocument;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;

import parser.EasyDLXParser;
import parser.ParseException;
import syntaxtree.Goal;
import syntaxtree.Node;


import easyDLXeditor.EasyDLXCursorPCTable;
import easyDLXeditor.EasyDLXCursors;
import easyDLXeditor.EasyDLXEditor;
import easyDLXeditor.EasyDLXTextLineNumber;
import easyDLXsimulation.EasyDLXALU;
import easyDLXsimulation.EasyDLXMachineGlobalState;
import easyDLXsimulation.EasyDLXSemanticError;
import easyDLXsimulation.EasyDLXMemoryManager;
import easyDLXvisitor.EasyDLXVisitorReferences;
import easyDLXvisitor.EasyDLXVisitorSimulation;
import easyDLXvisitor.EasyDLXVisitorTree;
/**
 * 
 * @author Daniele Biagi  biagi.daniele@gmail.com
 *
 */

public class EasyDLXJFrame extends javax.swing.JFrame {

	/** Creates new form EasyDLXJFrame */
	public EasyDLXJFrame() {
		initComponents();
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed" desc="Generated Code">
	private void initComponents() {

		editor=new EasyDLXEditor();
		editor.setSelectedTextColor(new Color(20,20,20));
		editor.setSelectionColor(Color.GREEN);
		h= editor.getHighlighter();

		jScrollPane1 = new javax.swing.JScrollPane(editor);
		tln = new EasyDLXTextLineNumber(editor);
		tln.setMinimumDisplayDigits(3);

		editor.addFocusListener(new FocusListener() {

			@Override
			public void focusLost(FocusEvent e) {
				// TODO Auto-generated method stub

			}

			@Override
			public void focusGained(FocusEvent e) {
				tln.setCurrentLineForeground(Color.DARK_GRAY);
				tln.repaint();
			}
		});


		setTitle("EasyDLX");
		setResizable(false);
		setIconImage(new ImageIcon(getClass().getResource("/easyDLXGUI/resources/frameicon.png")).getImage());
		setBounds(200, 100, 0, 0);
		jScrollPane1.setRowHeaderView( tln );

		jLayeredPane1 = new javax.swing.JLayeredPane();
		jResetButton = new javax.swing.JButton();
		jRunButton = new javax.swing.JButton();
		jStepButton = new javax.swing.JButton();
		jInitialAddrLabel = new javax.swing.JLabel();
		jInitialAddrTextField = new javax.swing.JTextField();
		jScrollPane2 = new javax.swing.JScrollPane();
		jMessagesTextArea = new javax.swing.JTextArea();
		jScrollPane3 = new javax.swing.JScrollPane();
		jScrollPane4 = new javax.swing.JScrollPane();
		jRegistersTextArea = new javax.swing.JTextArea();
		jScrollPane5 = new javax.swing.JScrollPane();
		jLabelsTextArea = new javax.swing.JTextArea();
		jScrollPane6 = new javax.swing.JScrollPane();
		jMemoryTextArea = new javax.swing.JTextArea();
		jMenuBar1 = new javax.swing.JMenuBar();
		jMenu1 = new javax.swing.JMenu();
		jFileMenuItem = new javax.swing.JMenuItem();
		jOpenMenuItem = new javax.swing.JMenuItem();
		jSaveMenuItem = new javax.swing.JMenuItem();
		jExitMenuItem = new javax.swing.JMenuItem();
		jMenu2 = new javax.swing.JMenu();
		jGrammarMenuItem = new javax.swing.JMenuItem();
		jAboutMenuItem = new javax.swing.JMenuItem();

		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

		jLayeredPane1.setBorder(javax.swing.BorderFactory.createTitledBorder("Controls"));

		jResetButton.setText("Stop");


		jResetButton.setBounds(40, 60, 120, 23);
		jLayeredPane1.add(jResetButton, javax.swing.JLayeredPane.DEFAULT_LAYER);

		jRunButton.setText("Run");
		jRunButton.setBounds(20, 20, 80, 30);
		jLayeredPane1.add(jRunButton, javax.swing.JLayeredPane.DEFAULT_LAYER);

		jStepButton.setText("Step");
		jStepButton.setEnabled(false);
		jStepButton.setBounds(110, 20, 80, 30);
		jLayeredPane1.add(jStepButton, javax.swing.JLayeredPane.DEFAULT_LAYER);

		jInitialAddrLabel.setText("Initial Address (hex):");
		jInitialAddrLabel.setAlignmentY(0.0F);
		jInitialAddrLabel.setBounds(10, 92, 110, 20);
		jInitialAddrLabel.setFont(new Font(jInitialAddrLabel.getFont().getName(),jInitialAddrLabel.getFont().getStyle(),jInitialAddrLabel.getFont().getSize()-2));
		jLayeredPane1.add(jInitialAddrLabel, javax.swing.JLayeredPane.DEFAULT_LAYER);
		jInitialAddrTextField.setBounds(110, 90, 90, 20);
		jInitialAddrTextField.setText("100000");
		jLayeredPane1.add(jInitialAddrTextField, javax.swing.JLayeredPane.DEFAULT_LAYER);

		jScrollPane2.setBorder(javax.swing.BorderFactory.createTitledBorder("Messages"));

		jMessagesTextArea.setColumns(20);
		jMessagesTextArea.setRows(5);
		jMessagesTextArea.setEditable(false);
		jScrollPane2.setViewportView(jMessagesTextArea);

		jScrollPane3.setBorder(javax.swing.BorderFactory.createTitledBorder("Syntax Tree"));

		//add syntax tree part:
		sintaxTree.setModel(null);
		sintaxTree.setSelectionModel(null);
		jScrollPane3.setViewportView(sintaxTree);




		jScrollPane4.setBorder(javax.swing.BorderFactory.createTitledBorder("Registers"));

		//jRegistersTextArea.setFont(new Font(jRegistersTextArea.getFont().getName(), jRegistersTextArea.getFont().getStyle(), jRegistersTextArea.getFont().getSize()-2));
		jRegistersTextArea.setFont(new Font(jRegistersTextArea.getFont().getName(), Font.PLAIN, jRegistersTextArea.getFont().getSize()-2));
		jRegistersTextArea.setColumns(20);
		jRegistersTextArea.setRows(5);
		jRegistersTextArea.setEditable(false);
		jScrollPane4.setViewportView(jRegistersTextArea);

		jScrollPane5.setBorder(javax.swing.BorderFactory.createTitledBorder("Labels"));

		jLabelsTextArea.setColumns(15);
		jLabelsTextArea.setRows(5);
		jLabelsTextArea.setEditable(false);
		jScrollPane5.setViewportView(jLabelsTextArea);

		jScrollPane6.setBorder(javax.swing.BorderFactory.createTitledBorder("Memory"));

		jMemoryTextArea.setColumns(15);
		jMemoryTextArea.setRows(5);
		jMemoryTextArea.setEditable(false);
		jScrollPane6.setViewportView(jMemoryTextArea);

		//MENU:

		jMenu1.setText("File");

		jFileMenuItem.setText("New");
		jFileMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK));
		jFileMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/easyDLXGUI/resources/new.png"))); 
		jFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				newActionPerformed(evt);
			}


		});
		jMenu1.add(jFileMenuItem);

		jOpenMenuItem.setText("Open");
		jOpenMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, java.awt.event.InputEvent.CTRL_MASK));
		jOpenMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/easyDLXGUI/resources/open.png")));
		jOpenMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				openActionPerformed(evt);
			}


		});
		jMenu1.add(jOpenMenuItem);

		jSaveMenuItem.setText("Save As");
		jSaveMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
		jSaveMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/easyDLXGUI/resources/save.png")));
		jSaveMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				saveActionPerformed(evt);
			}


		});
		jMenu1.add(jSaveMenuItem);
		jMenu1.add(new javax.swing.JPopupMenu.Separator());

		jExitMenuItem.setText("Close");
		jExitMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E, java.awt.event.InputEvent.CTRL_MASK));
		jExitMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/easyDLXGUI/resources/close.png")));
		jExitMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				closeActionPerformed(evt);
			}


		});


		jMenu1.add(jExitMenuItem);


		jMenuBar1.add(jMenu1);
		jMenu2.setText("Help");

		jGrammarMenuItem.setText("Grammar");
		jGrammarMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/easyDLXGUI/resources/grammar.png")));
		jGrammarMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, java.awt.event.InputEvent.CTRL_MASK));
		jGrammarMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				grammarActionPerformed(evt);
			}


		});


		jMenu2.add(jGrammarMenuItem);

		jAboutMenuItem.setText("About");
		jAboutMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/easyDLXGUI/resources/about.png")));
		jAboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				aboutActionPerformed(evt);
			}


		});


		jMenu2.add(jAboutMenuItem);

		jMenuBar1.add(jMenu2);

		setJMenuBar(jMenuBar1);
		restoreDefaultTextAreas();


		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(
				layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(layout.createSequentialGroup()
						.addContainerGap()
						.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 211, javax.swing.GroupLayout.PREFERRED_SIZE)
						.addGap(18, 18, 18)
						.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
								.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 218, Short.MAX_VALUE)
								.addComponent(jLayeredPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 218, Short.MAX_VALUE)
								.addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 209, javax.swing.GroupLayout.PREFERRED_SIZE))
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 201, javax.swing.GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
										.addComponent(jScrollPane6)
										.addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 186, Short.MAX_VALUE)))
				);
		layout.setVerticalGroup(
				layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
						.addContainerGap()
						.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
								.addComponent(jScrollPane4, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 482, Short.MAX_VALUE)
								.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
										.addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, 231, javax.swing.GroupLayout.PREFERRED_SIZE)
										.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
										.addComponent(jScrollPane6, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE))
										.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 482, Short.MAX_VALUE)
										.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
												.addComponent(jLayeredPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE)
												.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
												.addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 148, Short.MAX_VALUE)
												.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
												.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 200, javax.swing.GroupLayout.PREFERRED_SIZE)))
												.addContainerGap())
				);

		jRunButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {

				
				restoreDefaultTextAreas();
				sintaxTree.setModel(null);
				isInitialPCError=false;
				isParseError=false;
				semanticError= new EasyDLXSemanticError(false);
				long initialPC=0;

				try{

					initialPC= Long.parseLong(jInitialAddrTextField.getText().trim(), 16);
					initPC= Long.toBinaryString(initialPC);

					if (initPC.length()<32){
						initPC=EasyDLXMemoryManager.signExtentionTo32bits(initPC);
					}

					if (initPC.length()>32){
						initPC= initPC.substring(initPC.length()-32, initPC.length());
					}
					if ((Long.compare(initialPC, Long.parseLong("4294967295",10))>0)||(Long.compare(initialPC,0)<0)){
						isInitialPCError= true;
						setMessage("Wrong initial address format, it must be a hexadecimal number between 0 and ffffffff", true);
					}else{
						if (machine==null){
							machine= new EasyDLXMachineGlobalState(initPC);
						}else{
							machine.restartMachine(initPC);
						}
					}
				}catch(Exception ex){
					isInitialPCError= true;
					setMessage("Wrong initial address format, it must be a hexadecimal number", true);
				}
				if ((initialPC%4)!=0){
					isInitialPCError= true;
					setMessage("Wrong initial address, it must be a (hexadecimal) number divisible by 4", true);
				}
				if(!(editor.getText().trim().length()>0)){
					isInitialPCError= true;
					setMessage("Insert some instructions", true);
				}
				
				
				if (!isInitialPCError){
					startEvalutationGUIUpdate();
					
					isParseError= false;
					instructionIndex=0;
					
					instructions=buildInstructionsArray();
					numberOfIntstructions=computeNumberOfInstructions();
					
					parsedInstructions=0;
					cursorIndex=0;
					placeCursorToFirstInstr(false);
					
					references= new Hashtable<String,EasyDLXCursors>();
					cursorPCTable= new EasyDLXCursorPCTable();
					while((parsedInstructions<(numberOfIntstructions))&&(!isParseError)&&(!semanticError.isError())){
						initParser(instructions[instructionIndex]);
						EasyDLXVisitorReferences easyDLXVisitorLabels= new EasyDLXVisitorReferences(machine,EasyDLXALU.add(initPC, EasyDLXMemoryManager.signExtentionTo32bits(Integer.toBinaryString(4*parsedInstructions)), false),cursorIndex,instructionIndex,references,semanticError,cursorPCTable);
						try
						{
							Goal s = parser.Goal();
							s.accept(easyDLXVisitorLabels);
						}catch (ParseException e)
						{
							isParseError= true;
							parseExceptionOperations(e);
						}

						if ((!isParseError)&&(!semanticError.isError())){
							placeCursorToNextInstruction(false);
							semanticError= new EasyDLXSemanticError(false);
						}
					}

					if (semanticError.isError()){
						finishEvalutationGUIUpdate();
						//System.out.println("cursorIndex:"+cursorIndex+ "instructions[instructionIndex]:"+instructions[instructionIndex]);
						selectErrorLine(cursorIndex-instructions[instructionIndex].length(), instructionIndex);
						setMessage(semanticError.getMessage() +tln.getCurrentLine(),true);
					}else{
						if (!isParseError){
							
							Enumeration<String> e = references.keys();
							while(e.hasMoreElements()){
								String lb= e.nextElement();
								if(machine.getLabelsManager().getStringAddress(lb)==null){
									semanticError.setError(true);
									finishEvalutationGUIUpdate();
									//draw red line:
									selectErrorLine(references.get(lb).getCursor()-instructions[references.get(lb).getInstructionIndex()].length()-1,references.get(lb).getInstructionIndex());
									setMessage("Unresolved reference: \""+ lb+"\""+ " at line"+tln.getCurrentLine() , true);
									break;
								}
							}
						}
					}

					if ((!isParseError)&&(!semanticError.isError())){
						instructionIndex=0;
						parsedInstructions=0;
						cursorIndex=0;
						placeCursorToFirstInstr(true);
						updateGUIMachineState();
						//now let's start the evalutation of the instructions step by step
					}
				}
			}
		});
		jStepButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {

				sintaxTree.setModel(null);
				semanticError= new EasyDLXSemanticError(false);
				h.removeAllHighlights();
				Goal s;

				EasyDLXCursors c= cursorPCTable.getCursor(machine.getRegistersManager().getCurrentPC());
				if (c!=null){
					instructionIndex=c.getInstructionIndex();
					cursorIndex= c.getCursor()-instructions[instructionIndex].length();
					highlightInstruction(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);
					//editor.select(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);
				}
				try
				{
					//	initParser(instructions[instructionIndex]);
					initParser(instructions[instructionIndex]);
					//VISIT
					EasyDLXVisitorSimulation v = new EasyDLXVisitorSimulation(machine, semanticError);

					s = parser.Goal();
					//System.out.println("instructionIndex:="+instructionIndex+"numberOfIntstructions"+(numberOfIntstructions));
					s.accept(v);


					if (semanticError.isError()){
						h.removeAllHighlights();
						
						finishEvalutationGUIUpdate();
						selectErrorLine(cursorIndex, instructionIndex);
						//System.out.println("cursorIndex:"+cursorIndex+ "instructions[instructionIndex]:"+instructions[instructionIndex]);
						setMessage(semanticError.getMessage() +tln.getCurrentLine(),true);
						return;

					}else{
						setMessage("Successful Evaluation",false);

						//draw syntax tree:
						EasyDLXVisitorTree treeVisitor = new EasyDLXVisitorTree();
						s.accept(treeVisitor);
						dmtn = treeVisitor.getTree();

						DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
						renderer.setOpenIcon(null);
						renderer.setClosedIcon(null);
						renderer.setLeafIcon(null);
						sintaxTree.setCellRenderer(renderer);
						sintaxTree.setModel(GetTree());

						c= cursorPCTable.getCursor(machine.getRegistersManager().getCurrentPC());
						if (c!=null){
							instructionIndex=c.getInstructionIndex();
							cursorIndex= c.getCursor()-instructions[instructionIndex].length();
							highlightInstruction(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);
							editor.select(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);
						}else{
							h.removeAllHighlights();
							finishEvalutationGUIUpdate();
						}
						updateGUIMachineState();
					}
				}
				catch (ParseException e)
				{
					parseExceptionOperations(e);
				}
			}
		});
		
		jResetButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				h.removeAllHighlights();
				finishEvalutationGUIUpdate();
				
			}
		});

		pack();
	}// </editor-fold>


	/**
	 * @param args the command line arguments
	 */
	public static void main(String args[]) {
		/* Set the Nimbus look and feel */
		//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
		/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
		 * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
		 */
		try {
			for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
				if ("Nimbus".equals(info.getName())) {
					javax.swing.UIManager.setLookAndFeel(info.getClassName());
					break;
				}
			}
		} catch (ClassNotFoundException ex) {
			java.util.logging.Logger.getLogger(EasyDLXJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		} catch (InstantiationException ex) {
			java.util.logging.Logger.getLogger(EasyDLXJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		} catch (IllegalAccessException ex) {
			java.util.logging.Logger.getLogger(EasyDLXJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		} catch (javax.swing.UnsupportedLookAndFeelException ex) {
			java.util.logging.Logger.getLogger(EasyDLXJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
		}
		//</editor-fold>

		/* Create and display the form */
		java.awt.EventQueue.invokeLater(new Runnable() {

			public void run() {
				new EasyDLXJFrame().setVisible(true);
			}
		});
	}


	private void newActionPerformed(ActionEvent evt) {
		h.removeAllHighlights();
		finishEvalutationGUIUpdate();
		editor.setText("");
		sintaxTree.setModel(null);
		restoreDefaultTextAreas();

	}

	private void openActionPerformed(ActionEvent evt) {

		h.removeAllHighlights();
		finishEvalutationGUIUpdate();
		editor.setText("");
		sintaxTree.setModel(null);
		restoreDefaultTextAreas();

		EasyDLXDefaultFileChooser dc = new EasyDLXDefaultFileChooser(extension);
		File file = null;

		if (dc.showOpenDialog(this) == EasyDLXDefaultFileChooser.APPROVE_OPTION) {
			file = dc.getSelectedFile();
		} else {
			return;
		}

		if (file == null) {
			return;
		}

		try {
			int c;
			String str = "";
			InputStreamReader reader = new FileReader(file);

			while ((c = reader.read()) > 0) {
				str += (char) c;
			}

			reader.close();
			editor.setText(str);
		} catch (IOException e) {
			jMessagesTextArea.setForeground(Color.red);
			jMessagesTextArea.setText("An error has occured while file opening\n");
			jMessagesTextArea.setSelectionStart(0);
			jMessagesTextArea.setSelectionEnd(0);

		}
	}

	private void saveActionPerformed(ActionEvent evt) {

		File file = null;
		try {
			EasyDLXDefaultFileChooser dc = new EasyDLXDefaultFileChooser(extension);
			EasyDLXYesNoDialog yed = null;

			if (dc.showSaveDialog(this) == EasyDLXDefaultFileChooser.APPROVE_OPTION) {
				file = new File(dc.getSelectedFile().toString() + ".dlx");
				if (file.exists()) {
					yed = new EasyDLXYesNoDialog(file.getName());
					if (yed.setVisible() != 0) {
						saveActionPerformed(null);
						return;
					}
				}
			} else {
				return;
			}

			if (file == null) {
				return;
			}
		} catch (Exception e) {
			return;
		}

		try {
			OutputStreamWriter writer = new FileWriter(file);
			String str = editor.getText();
			writer.write(str);
			writer.flush();
			writer.close();
		} catch (IOException e) {
			jMessagesTextArea.setForeground(Color.red);
			jMessagesTextArea.setText("An error has occured while file saving\n");
			jMessagesTextArea.setSelectionStart(0);
			jMessagesTextArea.setSelectionEnd(0);
		}

	}
	private void closeActionPerformed(ActionEvent evt) {
		dispose();
		 System.exit(0);
	}

	private void aboutActionPerformed(ActionEvent evt) {

		ImageIcon icon = new ImageIcon(getClass().getResource("/easyDLXGUI/resources/EasyDLXLOGO.png"));
		String aboutGreeting = "EasyDLX\n\nAuthor: Daniele Biagi\nEmail: biagi.daniele@gmail.com";

		JFrame frame= new JFrame("About EasyDLX");
		frame.setIconImage(new ImageIcon(getClass().getResource("/easyDLXGUI/resources/frameicon.png")).getImage());
		JPanel panel= new JPanel();
		frame.add(panel);
		frame.setAlwaysOnTop(true);
		JLabel labelcredits= new JLabel();
		labelcredits.setIcon(icon);
		panel.add(labelcredits);
		JTextArea textAreaCredits= new JTextArea(aboutGreeting);
		textAreaCredits.setEditable(false);
		textAreaCredits.setBackground(panel.getBackground());

		panel.add(textAreaCredits);
		frame.setBounds(200, 100, 0, 0);
		frame.pack();
		frame.setVisible(true);
		frame.setResizable(false);

	}

	private void grammarActionPerformed(ActionEvent evt) {
		// TODO add your handling code here:

		File f=null;

		JFrame grammaticaFrame = new JFrame("EasyDLX Grammar");
		grammaticaFrame.setIconImage(new ImageIcon(getClass().getResource("/easyDLXGUI/resources/frameicon.png")).getImage());
		JEditorPane page = new JEditorPane();
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());
		URL baseUrl = null;
		try {
			f = new File(getClass().getResource("/easyDLXGUI/resources/EasyDLXv0.50.html").toURI());
			baseUrl = f.toURI().toURL();
		} catch (MalformedURLException ex) {
			ex.printStackTrace();
		} catch (URISyntaxException e) {

			e.printStackTrace();
		}
		page.setContentType("text/html");
		Container gc = grammaticaFrame.getContentPane();
		gc.add(panel);
		if (f!=null){
			try {
				FileInputStream fis1 = new FileInputStream(f);
				page.read(fis1, null);
			} catch (FileNotFoundException a) {
				a.printStackTrace();
			} catch (IOException a) {
				a.printStackTrace();
			}
		}
		HTMLDocument htmlDoc = (HTMLDocument) page.getDocument();
		htmlDoc.setBase(baseUrl);
		page.setEditable(false);
		JScrollPane st = new JScrollPane(page);
		st.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		st.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		st.setPreferredSize(new Dimension(800, 600));
		panel.add(st, BorderLayout.PAGE_START);
		grammaticaFrame.pack();
		grammaticaFrame.setResizable(false);
		grammaticaFrame.setVisible(true);

	}

	private String [] buildInstructionsArray() {
		return editor.getText().split("\n");
	}
	public void setMessage(String msg, boolean isError) {

		Color color= Color.black;
		if (isError){
			color=Color.red;
		}

		if (isParseError){
			jMessagesTextArea.setForeground(Color.red);

			int last_index=msg.indexOf(", column");
			int first_index= msg.indexOf("at line");
			//System.out.println(msg);
			//System.out.println((first_index+"at line".length())+"- "+(last_index));
			String toreplace=msg.substring(first_index+"at line".length()+1,last_index);
			//System.out.println(toreplace);
			//jMessagesTextArea.setText(msg.replaceFirst(toreplace, tln.getTextLineNumber(cursorIndex-instructions[instructionIndex].length())+""));
			jMessagesTextArea.setText(msg.replaceFirst(toreplace, tln.getCurrentLine()+""));
		}else{
			jMessagesTextArea.setForeground(color);
			jMessagesTextArea.setText(msg);
		}
		jMessagesTextArea.setSelectionStart(0);
		jMessagesTextArea.setSelectionEnd(0);

	}

	private void restoreDefaultTextAreas() {
		jLabelsTextArea.setText(labels_text_area_default);
		jMemoryTextArea.setText(memory_text_area_default);
		jRegistersTextArea.setText(registers_text_area_default);
		jRegistersTextArea.setSelectionStart(0);
		jRegistersTextArea.setSelectionEnd(0);
		jMessagesTextArea.setText(messages_text_area_default);
	}

	private int computeNumberOfInstructions() {
		int result=0;
		for (int i=0; i<instructions.length; i++){
			if (instructions[i].trim().length()>0){
				result++;
				//debug:
				//System.out.println(i+":"+instructions[i]+" "+instructions[i].length());
				if (!instructions[i].endsWith("\r")){
					instructions[i]= instructions[i]+"\r";
				}
			}
		}
		return result;
	}

	private void placeCursorToFirstInstr(boolean highlight) {
		if (highlight){
			highlightInstruction(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);
		}
		editor.select(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);
		cursorIndex=instructions[instructionIndex].length()+cursorIndex;
		while((instructions[instructionIndex].trim().length()==0)){
			nextInstruction(highlight);
		}
	}

	private void placeCursorToNextInstruction(boolean isEvalutation) {

		parsedInstructions++;
		if (parsedInstructions<(numberOfIntstructions)){
			do{
				nextInstruction(isEvalutation);
			}while((instructions[instructionIndex].trim().length()==0));
		}else{
			if (isEvalutation){
				finishEvalutationGUIUpdate();
			}
		}
	}

	private void initParser(String instruction) {
		
		if(parser==null){
			parser = new EasyDLXParser(new StringReader(instruction));
		}else{
			//debug
			//System.out.println(instruction);
			EasyDLXParser.ReInit(new StringReader(instruction));
		}

	}

	private void highlightInstruction(int start, int end) {
		if(!editor.isEditable()){
			try {
				h.removeAllHighlights();
				h.addHighlight(start, end, new DefaultHighlighter.DefaultHighlightPainter(new Color(152,243,97)));
			}catch (BadLocationException e) {
				e.printStackTrace();
			}
		}
	}
	private void finishEvalutationGUIUpdate() {

		jStepButton.setEnabled(false);
		jRunButton.setEnabled(true);
		editor.setEditable(true);
		jInitialAddrTextField.setEditable(true);

	}
	private void startEvalutationGUIUpdate() {
		jStepButton.setEnabled(true);
		jRunButton.setEnabled(false);
		editor.setEditable(false);
		jInitialAddrTextField.setEditable(false);
		jMessagesTextArea.setText("");
	}
	private void nextInstruction(boolean isEvalutation) {
		instructionIndex++;
		if (isEvalutation){
			highlightInstruction(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);

		}
		editor.select(cursorIndex, cursorIndex+instructions[instructionIndex].length()-1);
		cursorIndex=instructions[instructionIndex].length()+cursorIndex;
	}

	private void drawRedLine() {

		editor.select(cursorIndex-instructions[instructionIndex].length(), cursorIndex-1);
		tln.setCurrentLineForeground(Color.RED);
		tln.repaint();

	}


	private void parseExceptionOperations(ParseException e) {
		isParseError= true;
		setMessage(e.getMessage(),true);
		finishEvalutationGUIUpdate();
		drawRedLine();
		//System.out.println("EasyDLX Parser: Encountered errors during parse.");
		e.printStackTrace();
	}

	private void updateGUIMachineState() {
		jLabelsTextArea.setText(machine.getLabelsManager().toString());
		jLabelsTextArea.setSelectionStart(0);
		jLabelsTextArea.setSelectionEnd(0);


		jMemoryTextArea.setText(machine.getSimulatedMemory().toString());
		jMemoryTextArea.setSelectionStart(0);
		jMemoryTextArea.setSelectionEnd(0);


		jRegistersTextArea.setText(machine.getRegistersManager().toString());
		jRegistersTextArea.setSelectionStart(0);
		jRegistersTextArea.setSelectionEnd(0);
	}

	private void selectErrorLine(int cur, int i) {

		//System.out.println("cur:"+cur);
		editor.select(cur,cur+instructions[i].length()-1);
		tln.setCurrentLineForeground(Color.RED);
		tln.repaint();
	}

	private TreeModel GetTree() {
		return new DefaultTreeModel(dmtn);
	}


	// Variables declaration - do not modify
	private javax.swing.JButton jResetButton;
	private javax.swing.JButton jRunButton;
	private javax.swing.JButton jStepButton;
	private javax.swing.JLabel jInitialAddrLabel;
	private javax.swing.JLayeredPane jLayeredPane1;
	private javax.swing.JMenu jMenu1;
	private javax.swing.JMenu jMenu2;
	private javax.swing.JMenuBar jMenuBar1;
	private javax.swing.JMenuItem jFileMenuItem;
	private javax.swing.JMenuItem jOpenMenuItem;
	private javax.swing.JMenuItem jSaveMenuItem;
	private javax.swing.JMenuItem jExitMenuItem;
	private javax.swing.JMenuItem jGrammarMenuItem;
	private javax.swing.JMenuItem jAboutMenuItem;
	private javax.swing.JScrollPane jScrollPane1;
	private javax.swing.JScrollPane jScrollPane2;
	private javax.swing.JScrollPane jScrollPane3;
	private javax.swing.JScrollPane jScrollPane4;
	private javax.swing.JScrollPane jScrollPane5;
	private javax.swing.JScrollPane jScrollPane6;
	private javax.swing.JTextArea jMessagesTextArea;
	private javax.swing.JTextArea jRegistersTextArea;
	private javax.swing.JTextArea jLabelsTextArea;
	private javax.swing.JTextArea jMemoryTextArea;
	private javax.swing.JTextField jInitialAddrTextField;


	public EasyDLXEditor editor;
	public EasyDLXTextLineNumber tln; 
	private EasyDLXParser parser;  //  @jve:decl-index=0:
	private String [] instructions;
	private int instructionIndex=0; 
	private int cursorIndex=0;
	private Highlighter h;
	private int numberOfIntstructions=0;
	private int parsedInstructions=0;
	private EasyDLXMachineGlobalState machine;
	private String initPC;
	private boolean isInitialPCError=false;
	private boolean isParseError=false;

	private EasyDLXSemanticError semanticError;
	private Hashtable<String, EasyDLXCursors> references;
	private EasyDLXCursorPCTable cursorPCTable;
	private JTree sintaxTree = new javax.swing.JTree();
	private DefaultMutableTreeNode dmtn;


	
	private final String extension = "dlx";
	private static String registers_text_area_default="PC:\nR0:\nR1:\nR2:\nR3:\nR4:\nR5:\nR6:\nR7:\nR8:\nR9:\nR10:\nR11:\nR12:\nR13:\nR14:\nR15:\nR16:\nR17:\nR18:\nR19:\nR20:\nR21:\nR22:\nR23:\nR24:\nR25:\nR26:\nR27:\nR28:\nR29:\nR30:\nR31:";
	private static String labels_text_area_default="";
	private static String memory_text_area_default="";
	private static String messages_text_area_default="";

	// End of variables declaration



}


